home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / Acere (PowerPlant, Game) 1.2 / AcereÄ.sit / Acereƒ / Code / CardWell.cp < prev    next >
Text File  |  1995-03-04  |  18KB  |  663 lines

  1. // ===========================================================================
  2. //    CardWell.cp                        ⌐1993 Metrowerks Inc. All rights reserved.
  3. // ===========================================================================
  4. //
  5. //    Class for an object that can draw itself and respond to mouse clicks
  6.  
  7. #ifdef PowerPlant_PCH
  8. #include PowerPlant_PCH
  9. #endif
  10.  
  11. #include "CardWell.h"
  12. #include "CardDeck.h"
  13. #include "CardDragTask.h"
  14. #include "WellDeck.h"
  15. #include "CTextDoc.h"
  16. #include "AcereApp.h"
  17. #include <LView.h>
  18. #include <LStream.h>
  19. #include <PP_Messages.h>
  20. #include <UDrawingState.h>
  21.  
  22. extern CTextDoc    *theDoc;
  23. extern    unsigned long     ourAvailRam;
  24.  
  25. // ---------------------------------------------------------------------------
  26. //        Ñ CreatePaneStream [static]
  27. // ---------------------------------------------------------------------------
  28. //    Return a new Pane object initialized using data from a Stream
  29.  
  30. CardWell*
  31. CardWell::CreateCardWell(
  32.     LStream    *inStream)
  33. {
  34.     return (new CardWell(inStream));
  35. }
  36.  
  37.  
  38. // ---------------------------------------------------------------------------
  39. //        Ñ CardWell()
  40. // ---------------------------------------------------------------------------
  41. //    Default Constructor
  42.  
  43. CardWell::CardWell()
  44.         : LPane()/*,
  45. /*          LDragAndDrop(UQDGlobals::GetCurrentPort(), this) */
  46. {
  47.     InitCard();
  48.     
  49. //    LPane::CalcPortFrameRect(itsHelpRect);
  50. }
  51.  
  52.  
  53. // ---------------------------------------------------------------------------
  54. //        Ñ CardWell(const CardWell&)
  55. // ---------------------------------------------------------------------------
  56. //    Copy Constructor
  57.  
  58. CardWell::CardWell(
  59.     const CardWell    &inOriginal)
  60.         : LPane(inOriginal)
  61.   /*    ,      LDragAndDrop(UQDGlobals::GetCurrentPort(), this) */
  62. {
  63.     InitCard();
  64.     
  65.     
  66.     LPane::CalcPortFrameRect(itsHelpRect);
  67. }
  68.  
  69.  
  70. // ---------------------------------------------------------------------------
  71. //        Ñ CardWell(SPaneInfo&)
  72. // ---------------------------------------------------------------------------
  73. //    Construct Pane from data in a struct
  74.  
  75. CardWell::CardWell(const SPaneInfo    &inPaneInfo/*, const SViewInfo &inViewInfo*/)
  76.          : LPane(inPaneInfo/*, inViewInfo*/)
  77. /*          LDragAndDrop(UQDGlobals::GetCurrentPort(), this) */
  78. {
  79. //    LView::LView(inPaneInfo, inViewInfo);
  80. //    InitPane(inPaneInfo);
  81.     InitCard();
  82. }
  83.  
  84.  
  85. // ---------------------------------------------------------------------------
  86. //        Ñ CardWell(LStream*)
  87. // ---------------------------------------------------------------------------
  88. //    Construct Pane from data in a Stream
  89.  
  90. CardWell::CardWell(
  91.     LStream    *inStream)
  92.          : LPane(inStream)
  93. /*    ,      LDragAndDrop(UQDGlobals::GetCurrentPort(), this) */
  94. {
  95. //    SPaneInfo    thePaneInfo;
  96. //    LView::LView(inStream);
  97. //    inStream->ReadData(&thePaneInfo, sizeof(SPaneInfo));
  98. //    InitPane(thePaneInfo);
  99.     InitCard();
  100. }
  101.  
  102.  
  103. void CardWell::InitCard(void)
  104. {
  105.     Rect    frame;
  106.  
  107.     LPane::CalcPortFrameRect(itsHelpRect);
  108.  
  109.     cardCanMove = isHighlighted = false;
  110.     itsCard = nil;
  111.     
  112.     itsCardRgn = NewRgn();
  113.     
  114.     OpenRgn();
  115.     CalcPortFrameRect(frame);
  116.     FrameRoundRect(&frame, 20, 20);
  117.     CloseRgn(itsCardRgn);
  118.  
  119. }
  120.  
  121.  
  122. // ---------------------------------------------------------------------------
  123. //        Ñ ~CardWell
  124. // ---------------------------------------------------------------------------
  125. //    Destructor
  126.  
  127. CardWell::~CardWell()
  128. {
  129.     PutInside(nil);
  130.     
  131.     if (sLastPaneClicked == this) {
  132.         sLastPaneClicked = nil;
  133.     }
  134.     
  135.     DisposeRgn(itsCardRgn);
  136. }
  137.  
  138.  
  139. // ---------------------------------------------------------------------------
  140. //        Ñ Draw
  141. // ---------------------------------------------------------------------------
  142. //    Try to draw contents of a Pane
  143. //
  144. //    inSuperDrawRgnH specifies, in Port coordinates, the portion of the
  145. //    Pane's SuperView that needs to be drawn. Specify nil to bypass
  146. //    the intersection test.
  147. //    
  148. //    This is a wrapper function which calls DrawSelf if it is proper for
  149. //    the Pane to draw. This means that:
  150. //        > Pane's Visible property is on
  151. //        > Pane can be focused
  152. //        > Pane's Frame is in QuickDraw space
  153. //        > Pane's Frame intersects inSuperDrawRgnH
  154.  
  155. void    CardWell::Draw(RgnHandle inSuperDrawRgnH)
  156. {
  157.     Rect    frame;
  158.     if ( IsVisible()  &&
  159.          FocusDraw()  &&
  160.          CalcPortFrameRect(frame)  &&
  161.          ((inSuperDrawRgnH == nil) || RectInRgn(&frame, inSuperDrawRgnH)) )
  162.     {
  163.         DrawSelf();
  164.     }
  165. }
  166.  
  167. void    CardWell::DrawSelf()
  168. {
  169.     Rect        frame;
  170.  
  171.     CalcPortFrameRect(frame);
  172.     
  173.     if (itsCard == nil)
  174.     {
  175.         EraseRgn(itsCardRgn);
  176.         FrameRgn(itsCardRgn);
  177.     }
  178.     else if (itsCard->card == kNoCard)
  179.     {
  180.         EraseRgn(itsCardRgn);
  181.         FrameRgn(itsCardRgn);
  182.     }
  183.     else
  184.     {
  185.         theDeck->DrawCard(itsCard, frame, isHighlighted);
  186.     }
  187. }
  188.  
  189. Boolean    CardWell::CanRemove(void)            //    can we remove cards from this pile?
  190. {
  191.     return (true);
  192. }
  193.  
  194. Boolean    CardWell::PointInDropArea(Point inGlobalPt)        //    is it in our drop area?
  195. {
  196.     return (true);
  197. }
  198.  
  199. Boolean    CardWell::CanDrop(PlayingCard *draggedCard)
  200. {
  201.     if (itsCard == nil)
  202.         return (CanDropOnEmptySlot(draggedCard));
  203.     else if (itsCard->card == kNoCard)
  204.         return (CanDropOnEmptySlot(draggedCard));
  205.     else
  206.         return (CanDropOnSlot(draggedCard));
  207. }
  208.  
  209. Boolean    CardWell::ItemIsAcceptable(
  210.         DragReference    inDragRef,
  211.         ItemReference    inItemRef)
  212. {
  213.     return (CanDrop((PlayingCard *)inItemRef));
  214. }
  215.  
  216. /*void    CardWell::EnterDropArea(DragReference inDragRef, Boolean inDragHasLeftSender)
  217. //
  218. // The cursor has just entered our area.
  219. //
  220. {    // protected, virtual
  221.     // Let LDragAndDrop do its thing (hilight the area)
  222.     LDragAndDrop::EnterDropArea(inDragRef, inDragHasLeftSender);
  223.     
  224.     // And we'll do ours.
  225. //    PlaySound(gPlayEnterSound, rsrc_EnterSound);
  226. }
  227.  
  228.  
  229. void    CardWell::LeaveDropArea (DragReference inDragRef)
  230. //
  231. // The cursor has just left the building. I repeat, the cursor has left the building.
  232. //
  233. {    // protected, virtual
  234.     // Let LDragAndDrop do its thing (removes the hilighting)
  235.     LDragAndDrop::LeaveDropArea (inDragRef);
  236.     
  237.     // And we'll do ours.
  238. //    PlaySound(gPlayExitSound, rsrc_ExitSound);
  239. }
  240.  
  241.  
  242. void    CardWell::InsideDropArea (DragReference inDragRef)
  243. //
  244. // The cursor is still in our area.
  245. //
  246. {    // protected, virtual
  247.     
  248.     //
  249.     // Let LDragAndDrop do its thing - this is not really necessary, since
  250.     //        the inherited version doesn't do anything. But it's safer this
  251.     //        way because someday it might.
  252.     //
  253.     LDragAndDrop::InsideDropArea(inDragRef);
  254.     
  255.     //
  256.     // And we'll do ours - we'll just read the mouse coordinates, but for this
  257.     // demo we won't do anything with them.
  258.     //
  259.     // The mouse location is where the mouse actually is on the screen. The
  260.     // alternative is the pinned location, which is _usually_ the same location,
  261.     // but can be different if the cursor is being constrained by a tracking handler.
  262.     // This is useful when you want an area within a view to be 'off-limits' to
  263.     // the ongoing drag.
  264.     //
  265.     // If we did want to do something based on where the cursor currently is in
  266.     // our area (such as indicating an insertion point or something), it would
  267.     // usually be best to use the pinned location for that work.
  268.     //
  269.     // Both mouse locations are returned in global screen coordinates
  270.     //
  271.     Point    theMouseLocation;
  272.     Point    thePinnedLocation;
  273.     ::GetDragMouse(inDragRef, &theMouseLocation, &thePinnedLocation);
  274. }
  275.  
  276.  
  277. void    CardWell::ReceiveDragItem(
  278.     DragReference    inDragRef,
  279.     DragAttributes    inDragAttrs,
  280.     ItemReference    inItemRef,
  281.     Rect            &inItemBounds)    // In Local coordinates
  282. //
  283. // The user has dropped something in this view.
  284. //
  285. {
  286. //    PlaySound(gPlayDropSound, rsrc_DropSound);
  287.     ::InvalRect(&inItemBounds);
  288.     
  289.     //
  290.     // First, we'll figure out whether we want to copy the item(s), or only move the item(s).
  291.     //
  292.     // The rules for copying vs moving are spelled out in MD+DDK pp 19 through 21, and in
  293.     // a simplified form are: copy the item unless where it's coming from and
  294.     // where it's going to are the same window; then move it. If the option key
  295.     // was held down when the drag began, always copy it.
  296.     //
  297.     // Optional behaviour is for an application to also check the option
  298.     // key at the end of the drag. Copying then takes place if the option key was
  299.     // held down at the beginning _OR_ at the end.
  300.     //
  301.     Boolean optionKeyWasDown = CheckForOptionKey(inDragRef);
  302.     //
  303.     // Check to see if this View (the destination) is the
  304.     // same view (the source) that the object is coming from.
  305.     //
  306.     Boolean dragIsFromThisView = CheckIfViewIsAlsoSender(inDragRef);
  307.     
  308.     //
  309.     // Information about the drag contents we'll be needing.
  310.     //
  311.     FlavorFlags            theFlags;        // We actually only use the flags to see if a flavor exists
  312.     Size                theDataSize;    // How much data there is for us.
  313.     CardStruct            tCard;    // Where we will put that data.
  314.     
  315.     //
  316.     // Check to make sure the drag contains a cItemType item.
  317.     //
  318.     if (GetFlavorFlags(inDragRef, inItemRef, cCardWellType, &theFlags) == noErr) {
  319.         ::GetFlavorDataSize(inDragRef, inItemRef, cCardWellType, &theDataSize);
  320.         if (theDataSize) {
  321.             ThrowIf_(theDataSize != sizeof(CardStruct));    // sanity check
  322.             //
  323.             // Get the data about the rectangle we are receiving.
  324.             //
  325.             ::GetFlavorData(inDragRef, inItemRef, cCardWellType, &tCard, &theDataSize, 0L);
  326.             PlayingCard* theReceivedItem;
  327.             //
  328.             // Decide whether we want to move it or to make a new copy for ourselves
  329.             //
  330.             if (dragIsFromThisView && !optionKeyWasDown) {
  331.                 //
  332.                 // Move the item within this window
  333.                 //
  334.                 // Since we know it came from this window to this window,
  335.                 // the pointer must still be good. This is the _only_ time we
  336.                 // can rely on the pointer field in the structure.
  337.                 //
  338.                 // If you come up with (or already know of) a nicer way of
  339.                 // managing this, please let me know. (gdignard@hookup.net)
  340.                 //
  341. //ÑÑ                theReceivedItem = tCard.vPointerToSourceObject;
  342.             } else {
  343.                 //
  344.                 // Make a new copy of the dragged item
  345.                 //
  346.                 theReceivedItem = new PlayingCard(&tCard);
  347.             }
  348.             //
  349.             // Place it correctly in the view
  350.             //
  351.             // Check to see if the drag includes an HFS flavor. If it does, it means
  352.             // the flavor is coming from a clipping. This will be useful to know, since
  353.             // if the drag includes an HFS flavor, it means the user is dragging a file
  354.             // (ie in our case, a clipping). Since the user is dragging a file, the visual
  355.             // feedback they are getting is the outline of a file, not of the item. For that
  356.             // reason we'll want to drop the item centered around the current mouse position.
  357.             //
  358.             // If you want to actually see what this was designed to fix, change the !fromFinder
  359.             // in the following test to true, and drag from a clipping file to a CDDView.
  360.             //
  361.             Boolean fromFinder = (GetFlavorFlags(inDragRef, inItemRef,
  362.                                             flavorTypeHFS, &theFlags) == noErr);
  363.             
  364.             if (!fromFinder) {
  365.                 //
  366.                 // Put it where the user dropped the item
  367.                 //
  368.                 theReceivedItem->PlaceInSuperFrameAt(inItemBounds.left, inItemBounds.top, true);
  369.             } else {
  370.                 //
  371.                 // It came from the Finder, place it centered around the drop point.
  372.                 //
  373. //                theReceivedItem->PlaceInSuperFrameAt(
  374. //                                        inItemBounds.left - tCard.vItemSize.width / 2,
  375. //                                        inItemBounds.top - tCard.vItemSize.height / 2,
  376. //                                        true);
  377.             }
  378.             
  379.             //
  380.             // If this view is on duty, make the received item the target
  381.             //
  382. //            if (IsOnDuty()) {
  383. //                SwitchTarget(theReceivedItem);
  384. //            }
  385.         }
  386.     }
  387. }
  388.  
  389.  
  390. Boolean    CardWell::CheckForOptionKey(DragReference inDragRef)
  391. {    // private
  392.     //
  393.     // We'll check whether the option key was down at either the beginning _or_ the
  394.     // end of the drag, since (a) it's the preferred behaviour and (b) its so easy to do.
  395.     //
  396.     Int16 theModifiersNow;            // The state of the modifier keys right now
  397.     Int16 theModifiersAtMouseDown;    // The state of the modifier keys when the drag began
  398.     Int16 theModifiersAtMouseUp;    // The state of the modifier keys when the drag ended
  399.     ::GetDragModifiers(inDragRef, &theModifiersNow, &theModifiersAtMouseDown, &theModifiersAtMouseUp);
  400.     
  401.     return ((theModifiersAtMouseDown & optionKey) || (theModifiersAtMouseUp & optionKey));
  402. }
  403.  
  404.  
  405. Boolean    CardWell::CheckIfViewIsAlsoSender(DragReference inDragRef)
  406. {    // private
  407.     //
  408.     // Just a note: While we are using the drag attributes only at the end of the
  409.     // drag, they are also available to you during the drag.
  410.     //
  411.     // Drag Attributes are described in MD+DDK, page 2-31.
  412.     //
  413.     DragAttributes theDragAttributes;
  414.     ::GetDragAttributes(inDragRef, &theDragAttributes);
  415.     
  416.     return (theDragAttributes & dragInsideSenderWindow);
  417. }
  418.  
  419. */
  420.  
  421. Boolean    CardWell::CanDropOnEmptySlot(PlayingCard *draggedCard)
  422. {
  423.     //    this will be overridden by most subclasses, which is why it's separate
  424.     //    default behavior is that ANY card can be dropped on an empty slot
  425.     
  426.     return (true);
  427. }
  428.  
  429. Boolean    CardWell::CanDropOnSlot(PlayingCard *draggedCard)
  430. {
  431.     //    this will be overridden by most subclasses.
  432.     //    default behavior is that no card can be dropped on any card.
  433.     
  434.     return (false);
  435. }
  436.     
  437.  
  438. void    CardWell::AddCardToWell(CardWell *whichWell, PlayingCard *whichCard)
  439. {
  440.     whichCard->itsOwner = this;
  441.     itsCard = whichCard;
  442. }
  443.  
  444.  
  445. void    CardWell::RemoveCardFromWell(CardWell *whichWell, PlayingCard *whichCard)
  446. {
  447.     itsCard = nil;
  448. }
  449.  
  450.  
  451. void    CardWell::Click(SMouseDownEvent &inMouseDown)
  452. {
  453.         CardWell    *firstOwner, *secondOwner;
  454.     
  455.     if ((itsCard == nil) && (theDoc->firstCard == nil))    //    don't bother if there's no card!
  456.         return;
  457.     
  458.     LPane::Click(inMouseDown);
  459.     
  460.     if (sClickCount > 1)            //    user double-clicked
  461.     {
  462.         short    j;
  463.         
  464.         for (j=0; j < 4; j++)
  465.         {
  466.             secondOwner = theDoc->theDeckWells[j];
  467.  
  468.             if (secondOwner->CanDrop(this->itsCard))
  469.             {
  470.                 firstOwner = this;
  471.  
  472.                 secondOwner->AddCardToWell(this, this->itsCard);
  473.                 
  474.                 this->RemoveCardFromWell(this, itsCard);
  475.  
  476.                 theDoc->firstCard = /*theDoc->secondCard = */ nil;
  477.                 
  478.                 firstOwner->isHighlighted = false;
  479.                 secondOwner->isHighlighted = false;
  480.                 
  481.                 firstOwner->Draw(nil);
  482.                 secondOwner->Draw(nil);
  483.                 
  484.                 return;
  485.             }
  486.             
  487.         }
  488.         
  489.     }
  490.     
  491.     if (theDoc->firstCard == nil)
  492.     {
  493.         if (CanRemove())
  494.         {
  495.             theDoc->firstCard = itsCard;
  496. //            theDoc->firstCard->itsCardInfo = itsCard->itsCardInfo;
  497.             isHighlighted = true;
  498. //            theDoc->firstCard->itsOwner->DrawSelf();
  499.             DrawSelf();
  500.         }
  501.         else
  502.             SysBeep(3);
  503.     }
  504.     else if (theDoc->firstCard == itsCard)    //    we're unclicking it
  505.     {
  506.         
  507.         isHighlighted = false;
  508.         DrawSelf();
  509.         theDoc->firstCard = nil;            //    toggle selection
  510.     }
  511.     else
  512.     {
  513. //        theDoc->secondCard = itsCard;
  514. //        theDoc->secondCard->itsCardInfo = itsCard->itsCardInfo;
  515.     
  516.         //    this is a little tricky -- we need to call the subclass's method
  517.         
  518.         if (itsCard == nil)    // can't use the card method since card doesn't exist
  519.         {
  520.             if (this->CanDropOnEmptySlot(theDoc->firstCard))
  521.             {
  522.                 firstOwner = theDoc->firstCard->itsOwner;
  523.                 secondOwner = this;
  524.                 
  525.                 
  526.                 theDoc->firstCard->itsOwner->RemoveCardFromWell(theDoc->firstCard->itsOwner, 
  527.                     theDoc->firstCard);
  528.                     
  529.                 secondOwner->AddCardToWell(this, theDoc->firstCard);
  530.             
  531.                 theDoc->firstCard = /*theDoc->secondCard = */ nil;
  532.                 
  533.                 firstOwner->isHighlighted = false;
  534.                 secondOwner->isHighlighted = false;
  535.                 
  536.                 firstOwner->DrawSelf();
  537.                 secondOwner->DrawSelf();
  538.             }
  539.         }
  540.         else if (this->CanDrop(theDoc->firstCard))
  541.         {
  542.             //    we can drag
  543.             
  544.             //    first we remove the card from its old slot
  545.             
  546.             firstOwner = theDoc->firstCard->itsOwner;
  547.             secondOwner = this;
  548.             
  549.             theDoc->firstCard->itsOwner->RemoveCardFromWell(theDoc->firstCard->itsOwner, 
  550.                     theDoc->firstCard);
  551.                     
  552.             //    then we add it to the second slot
  553.             
  554.             this->AddCardToWell(this, theDoc->firstCard);
  555.             
  556.             theDoc->firstCard = /*theDoc->secondCard = */ nil;
  557.             
  558.             firstOwner->isHighlighted = false;
  559.             secondOwner->isHighlighted = false;
  560.             
  561.             firstOwner->DrawSelf();
  562.             secondOwner->DrawSelf();
  563.             
  564.         }
  565.         else                //    we couldn't drop the card
  566.         {
  567. //            theDoc->secondCard = nil;
  568.             SysBeep(3);
  569.         }
  570.     }
  571. }
  572.  
  573. /*void    CardWell::ClickSelf(const SMouseDownEvent &inMouseDown)
  574. {
  575.     SwitchTarget(this);        // Make this item active
  576.     //
  577.     // Track item long enough to distinguish between a click to
  578.     // select, and the beginning of a drag
  579.     //
  580.     Boolean isDrag = ::WaitMouseMoved(inMouseDown.macEvent.where);
  581.     
  582.     if (isDrag) {
  583.         //
  584.         // If we leave the window, the drag manager will be changing thePort,
  585.         // so we'll make sure thePort remains properly set.
  586.         //
  587.         mSuperView->FocusDraw();
  588.         CreateDragEvent(inMouseDown);
  589.         mSuperView->OutOfFocus(nil);
  590.     }
  591. }
  592.  
  593. void CardWell::CreateDragEvent(const SMouseDownEvent &inMouseDown)
  594. {    // private
  595.  
  596.     if (itsCard->card == kNoCard)
  597.         return;        // can't drag nuttin'
  598.  
  599.     //
  600.     // We can create a Drag Task in one of two ways.
  601.     //
  602.     // The first is the quick and dirty way. The advantage is that you don't need
  603.     // to subclass LDragTask to drag the item. One disadvantage is that you don't
  604.     // get the opportunity to include a 'PICT' flavor in the drag. That means if
  605.     // the user double-clicks the item in the Finder he/she won't get a graphic
  606.     // depiction of the object. Another disadvantage is that we don't have the
  607.     // opportunity to define what the drag outline should look like. When we use
  608.     // LDragTask, the outline is always a rectangle.
  609.     //
  610.     // The second way is to subclass LDragTask, and have that subclass know about
  611.     // how to build a PICT of the current item to include in the drag, and also
  612.     // be able to define outlines customized to the item being dragged.
  613.     //
  614.     // You would normally choose one or the other way to go. I've done both so you
  615.     // can see how each is done. There's a menu item that allows you to switch back
  616.     // and forth between the two, so you can see the difference it makes to the user.
  617.     //
  618.  
  619.     //
  620.     // This rect is going to be used by the Drag Task to draw the
  621.     // outline as the user drags the item around. LDragTask converts
  622.     // this rect into a region, which is then passed to the drag manager
  623.     // so it knows what the drag outline should look like.
  624.     //
  625.     Rect theRect;
  626.     CalcLocalFrameRect(theRect);
  627.     //
  628.     // Build a structure to contain the data we'll be passing to the drag event.
  629.     //
  630.     CardStruct theFlavorData;
  631.     FillDataStruct(&theFlavorData);
  632.     //
  633.     // Begin the drag task
  634.     //
  635.     LDragTask theDragTask(    inMouseDown.macEvent, theRect, 1, cCardWellType,
  636.                             &theFlavorData, sizeof(theFlavorData), 0L);
  637.     //
  638.     // If the drag is to the trash, it should be a move, not a copy
  639.     //
  640. //    CheckForTrash(&theDragTask);
  641. }
  642.  
  643. void CardWell::FillDataStruct(CardStruct *theStruct)
  644. {
  645.         theStruct->suit = itsCard->suit;
  646.         theStruct->card = itsCard->card;
  647.         theStruct->color = itsCard->color;
  648.         theStruct->itsOwner = itsCard->itsOwner;
  649. //    itsCardInfo = *theStruct;
  650. }
  651. */
  652.  
  653. RgnHandle CardWell::GetCardRegion(void)
  654. {
  655.     return itsCardRgn;
  656. }
  657.  
  658. void    CopyPString(ConstStr255Param srcString, Str255 destString)
  659. {
  660.     BlockMove(srcString, destString, srcString[0] + 1L);
  661. }
  662.  
  663.